﻿package com.zouloux.ui 
{
	import com.zouloux.abstract.IComponent;
	import com.zouloux.core.display.DocumentClass;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class KnobButton extends GenericButton implements IComponent
	{
		// L'angle de départ au clic
		private var _startRotation				:Number;
		
		// L'angle minimum
		protected var _minAngle					:Number 		= Number.MIN_VALUE;
		
		// L'angle maximum
		protected var _maxAngle					:Number 		= Number.MAX_VALUE;
		
		// Le step
		protected var _step						:Number			= 0;
		
		// La valeur
		protected var _value					:Number			= 0;
		
		// L'inertie
		protected var _inertia					:uint			= 0;
		
		// Le centre
		protected var _center					:Point 			= new Point(0, 0);
		
		// Si on est en train de déplacer
		protected var _dragging					:Boolean;
		
		// La vitesse de rotation actuelle
		protected var _rotationSpeed			:Number;
		
		
		// Les getters
		public function get minAngle():Number { return _minAngle; }
		public function get maxAngle():Number { return _maxAngle; }
		public function get step():Number { return _step; }
		public function get value():Number { return _value; }
		public function get inertia():uint { return _inertia; }
		public function get center():Point { return _center; }
		public function get dragging():Boolean { return _dragging; }
		public function get rotationSpeed():Number { return _rotationSpeed; }
		
		
		// Les setters
		public function set minAngle(value:Number):void 
		{
			_minAngle = value;
		}
		public function set maxAngle(value:Number):void 
		{
			_maxAngle = value;
		}
		public function set step(value:Number):void 
		{
			_step = value;
		}
		public function set value(value:Number):void 
		{
			_value = value;
		}
		public function set inertia(value:uint):void 
		{
			_inertia = value;
		}
		public function set center(value:Point):void 
		{
			_center = value;
		}
		
		
		
		// Le contrôler
		public function KnobButton (pButtonMode:Boolean = true)
		{
			// Construire le parent
			super(pButtonMode);
			
			// On vire les effets de tween
			_tweenOver.clear();
			_tweenOut.clear();
			_tweenPress.clear();
			_tweenRelease.clear();
			
			// Ecouter les clics
			addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
			DocumentClass.stage.addEventListener(MouseEvent.MOUSE_UP, upHandler);
		}
		
		// Début de clic
		public function downHandler (event:MouseEvent = null):void
		{
			// On se déplace
			_dragging = true;
			
			// Se souvenir de la rotation actuelle
			_startRotation = calculateAngle() - rotation;
			
			// La boucle
			addEventListener(Event.ENTER_FRAME, moveLoopHandler);
		}
		
		// Relâchement de la souris
		public function upHandler (event:MouseEvent = null):void
		{
			// On se déplace plus
			_dragging = false;
			
			// Tuer la boucle
			if (_inertia == 0 || _rotationSpeed == 0)
				removeEventListener(Event.ENTER_FRAME, moveLoopHandler);
		}
		
		// La boucle
		protected function moveLoopHandler (event:Event = null):void
		{
			// S'il y a un parent
			if (parent != null)
			{
				// Si on est en train de déplacer
				if (_dragging)
				{
					// Calculer l'angle
					var angle:Number = calculateAngle();
					
					// Calculer la vitesse de rotation
					_rotationSpeed = - (rotation - (angle - _startRotation));
					
					// Vérifier si on a pas passé un tour complet
					if (Math.abs(_rotationSpeed) > 180)
						_rotationSpeed = - (rotation - (angle - _startRotation) + 360);
					
					// Appliquer la rotation
					rotation = (angle - _startRotation);
				}
				else
				{
					// Appliquer l'inertie
					_rotationSpeed *= _inertia / 100;
					
					// Appliquer la rotation
					rotation += _rotationSpeed;
					
					// Vérifier la fin
					if (Math.abs(_rotationSpeed) < 0.1)
						removeEventListener(Event.ENTER_FRAME, moveLoopHandler);
				}
			}
		}
		
		// Calculer l'angle
		protected function calculateAngle ():Number
		{
			// Calculer les distances
			var distanceX:Number = x - parent.mouseX + _center.x;
			var distanceY:Number = y - parent.mouseY + _center.y;
			
			// Calculer l'angle
			return -Math.atan2(distanceX, distanceY) / Math.PI * 180;
		}
	}
}